use std::sync::Arc;

use anyhow::{anyhow, Result};
use sea_orm::{ConnectionTrait, DatabaseBackend, DatabaseConnection, EntityTrait, IntoActiveModel, ModelTrait, Statement, TryIntoModel};
use tracing::info;
use crate::dto::point_dto::PointDto;
use crate::dto::point_group_dto::{AddPointGroupDto, BasePointGroupDto, PointGroupDto};

use crate::entity::{cfg_varsystem, pointgroups, pointpointgroup};
use crate::entity::cfg_varsystem::Relation::Pointpointgroup;
use crate::entity::pointgroups::Model;
use crate::entity::prelude::CfgVarsystem;
use crate::repo::point_repo::DbContextHolder;

pub struct PointGroupRepo {
    db_contexts: Arc<Vec<DatabaseConnection>>,
}

impl DbContextHolder for PointGroupRepo {
    fn get_db_contexts(&self) -> &Vec<DatabaseConnection> {
        &self.db_contexts
    }
}

impl PointGroupRepo {
    pub fn new(dbs: Arc<Vec<DatabaseConnection>>) -> Self {
        Self { db_contexts: dbs }
    }

    pub async fn get_all_point_groups_async(&self, machine_index: u32) -> Result<Vec<PointGroupDto>> {
        let db_context = self.get_db_context(machine_index);
        let ret = pointgroups::Entity::find().all(db_context).await?.iter().map(|x| PointGroupDto::from(x.clone())).collect();
        Ok(ret)
    }
    pub async fn add_point_group_async(&self, machine_index: u32, point_group: AddPointGroupDto) -> Result<Model> {
        let db_context = self.get_db_context(machine_index);
        let x: Model = point_group.into();
        let model = x.into_active_model();
        let model_clone = model.clone();
        pointgroups::Entity::insert(model).exec(db_context).await?;
        Ok(model_clone.try_into_model()?)
    }
    pub async fn get_point_group_by_id_async(&self, machine_index: u32, id: i32) -> Result<PointGroupDto> {
        let db_context = self.get_db_context(machine_index);
        let ret = pointgroups::Entity::find_by_id(id).one(db_context).await?.ok_or_else(|| anyhow!("未找到测点组"))?;
        let points = ret.find_related(CfgVarsystem).all(db_context).await?.iter().map(|x| PointDto::from(x.clone())).collect::<Vec<PointDto>>();
        let mut point_group_dto = PointGroupDto::from(ret);
        point_group_dto.points = points;
        Ok(point_group_dto)
    }
    pub async fn update_point_group_and_points(&self, machine_index: u32, point_group_id: i32, updated_point_group: BasePointGroupDto, updated_points: Vec<PointDto>) -> Result<()> {
        let db_context = self.get_db_context(machine_index);

        // 更新 PointGroup
        let mut point_group_model: pointgroups::Model = updated_point_group.into();
        point_group_model.id = point_group_id;
        let point_group_active_model = point_group_model.into_active_model();

        pointgroups::Entity::update(point_group_active_model).exec(db_context).await?;

        // 获取并更新关联的 Points
        let list = pointgroups::Entity::find_by_id(point_group_id).find_with_related(CfgVarsystem).all(db_context).await?;
        // 获取 related_points 的所有 ids
        let mut origin_point_ids = vec![];
        for (_, related_points) in list {
            for i in 0..related_points.len() {
                origin_point_ids.push(related_points[i].id);
            }
        }
        // 先删除 原来的关联
        for point_id in origin_point_ids {
            let sql = Statement::from_string(
                DatabaseBackend::MySql,
                format!(
                    "DELETE FROM pointpointgroup WHERE PointGroupsId = {} AND pointsId = {}",
                    point_group_id, point_id
                ));
            let result = db_context.execute(sql).await?;
            info!("删除关联结果: {:?}", result)
        }
        // 再创建原来的关联
        for point in updated_points {
            let sql = Statement::from_string(
                DatabaseBackend::MySql,
                format!(
                    "INSERT INTO pointpointgroup (PointGroupsId, pointsId) VALUES ({}, {})",
                    point_group_id, point.base.id
                ));
            let result = db_context.execute(sql).await?;
            info!("创建关联结果: {:?}", result)
        }

        Ok(())
    }
}

